<?php

namespace addons\travel\library\traits\model\order;

use addons\sum\exception\Exception;
use addons\sum\model\User;
use addons\travel\model\Goods as GoodsModel;
use addons\travel\model\Order;
use addons\travel\model\Service as ServiceModel;
use think\Cache;
use think\Db;


trait OrderOper
{
    // 获取订单号
    public static function getSn($user_id)
    {
        $rand = $user_id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999);
        $order_sn = date('Yhis') . $rand;

        $id = str_pad($user_id, (24 - strlen($order_sn)), '0', STR_PAD_BOTH);

        return $order_sn . $id;
    }

    // 计算订单
    public static function pre($params, $calc_type = 'pre')
    {
        $user = User::info();
        extract($params);
        $goods_price=0;
        $goods_or_home=null;
        // 商品信息
        $goods=GoodsModel::detail(['id'=>$goods_id,'lang_slug'=>$lang_slug]);
        //处理标签
        $goods_service_arr=[];
        $goods_service_text='';
        if(!empty($goods['service'])){
            foreach ($goods['service'] as $gsv){
                $goods_service_arr[]=$gsv['title'];
            }
            $goods_service_text=implode('/',$goods_service_arr);
        }
        $goods_or_home=$goods;
        $goods_price=$goods['price'];//商品价格

        //订房的时候-房间信息
        if(isset($goods_id_home)){
            $home=GoodsModel::detail(['id'=>$goods_id_home,'lang_slug'=>$lang_slug]);
            $goods_price=$home['price'];//商品价格是房间价格
            $goods_or_home=$home;
        }
        $car_route='';
        if($goods['type']=='house'){//订房
            $pretime=strtotime($pretime);
            $endtime=$pretime+$goods_num*86400;
        }
        if($goods['type']=='trip'){//旅游 trip_day
            $predate=$pretime;
            $pretime=strtotime($pretime);
            $endtime=$pretime+$goods['trip_day']*86400;
            // 处理特殊日期价格
            if(is_array($goods['date_price'])){
//                $goods['date_price']=json_decode($goods['date_price'],true);
                foreach ($goods['date_price'] as $gdpv){
                    if($predate==$gdpv['date']){
                        $goods_price=$gdpv['price'];
                    }
                }
            }


        }
        //20240621新增 订车加接送机类型
        if(!isset($car_type)){
            $car_type='no';
        }
        if($goods['type']=='car'){
            if($car_type=='jie'){
                $goods_price=$goods['price'];//接机价格
            }elseif ($car_type=='song'){
                $goods_price=$goods['price_song'];//送机价格
            }elseif ($car_type=='jands'){
                $goods_price=$goods['price_jands'];//往返价格
            }
            $car_route=$goods['subtitle'];//行车路线
        }
        if(!isset($endtime)){
            $endtime=strtotime($pretime);
        }
        $goods_type=$goods['type'];
        $goods_title=$goods['title'];
        $goods_subtitle=$goods['subtitle'];
        $goods_title_home=$home['title']??'';
        $goods_image=$goods['image']??'';
        //订单商品总额
        $total_amount=$goods_price*$goods_num;
        //订单总额 根据订单类型
        if($type=='goods'){
            $total_fee=$total_amount;
        }else{
            // activity 活动订单，不需要支付
            $total_fee=0;
        }

        // 需要处理小数点的数据
        $result = compact(
            "goods_price",
            "total_amount",
            "total_fee"
        );
        // 处理小数点保留两位小数
        foreach ($result as $key => $vo) {
            $result[$key] = number_format($vo, 2, '.', '');
        }
        // 合并不需要处理小数点的
        $result = array_merge($result, compact(
            "goods_type",
            "goods_title",
            "goods_title_home",
            "goods_image",
            "car_route",
            "goods_or_home",
            "endtime",
            "goods_service_text",
            "goods_subtitle"
        ));
        return $result;

    }

    /**
     * 创建订单
     * @param $params
     * @return mixed
     */
    public static function createOrder($params)
    {
        $user = User::info();
        // 入参
        extract($params);
        $remark = $remark ?? null;
        $pretime=strtotime($pretime);
        $passenger_num = $passenger_num ?? 0;
        $house_info = $house_info ?? null;
        // 订单计算数据
        extract(self::pre($params, "create"));
        $goods_id_home = $goods_id_home ?? 0;
        $goods_title_home = $goods_title_home ?? null;
        $car_route = $car_route ?? null;

        $car_type=$car_type??'no';

        $luggage_num = $luggage_num ?? 0;
        $flight_number = $flight_number ?? '';
        if(isset($flight_time)){
            $flight_time=strtotime($flight_time);
        }else{
            $flight_time=null;
        }

        $flight_number_song = $flight_number_song ?? '';
        if(isset($flight_time_song)){
            $flight_time_song=strtotime($flight_time_song);
        }else{
            $flight_time_song=null;
        }

        $order = Db::transaction(function () use (
            $type,//订单类型
            $user,
            $total_amount,
            $total_fee,
            $first_name,
            $last_name,
            $phone,
            $email,
            $goods_type,
            $goods_id,
            $goods_title,
            $goods_id_home,
            $goods_title_home,
            $goods_image,
            $goods_price,
            $goods_num,
            $pretime,
//            $starttime,
            $endtime,
            $passenger_num,
            $house_info,
            $car_route,
            $goods_or_home,
            $remark,
            $goods_service_text,
            $goods_subtitle,
            $luggage_num,
            $flight_number,
            $flight_time,
            $car_type,
            $flight_number_song,
            $flight_time_song
        ) {

            // 订单创建前
            $data = [
                'goods_or_home' => $goods_or_home,
            ];
            // 如果是活动，这里面减掉 redis 库存
            \think\Hook::listen('order_create_before', $data);
            $orderData = [];
            $orderData['type'] = $type;
            $orderData['order_sn'] = self::getSn($user->id);
            $orderData['user_id'] = $user->id;
            $orderData['total_amount'] = $total_amount;
            $orderData['total_fee'] = $total_fee;
            // 游客信息
            $orderData['first_name'] = $first_name;
            $orderData['last_name'] = $last_name;
            $orderData['phone'] = $phone;
            $orderData['email'] = $email;
            // 商品信息
            $orderData['goods_type'] = $goods_type;
            $orderData['goods_id'] = $goods_id;
            $orderData['goods_title'] = $goods_title;
            $orderData['goods_id_home'] = $goods_id_home;
            $orderData['goods_title_home'] = $goods_title_home;
            $orderData['goods_image'] = $goods_image;
            $orderData['goods_price'] = $goods_price;
            $orderData['goods_num'] = $goods_num;
            // 行程信息
            $orderData['pretime'] = $pretime;
//            $orderData['starttime'] = $starttime;
            $orderData['endtime'] = $endtime;
            // 不同类型扩展信息
            $orderData['passenger_num'] = $passenger_num;
            $orderData['house_info'] = $house_info;
            $orderData['car_route'] = $car_route;
            $order_ext['goods_service_text'] = $goods_service_text;
            $order_ext['goods_subtitle'] = $goods_subtitle;

            $orderData['luggage_num'] = $luggage_num;
            $orderData['flight_number'] = $flight_number;
            $orderData['flight_time'] = $flight_time;
            $orderData['car_type'] = $car_type;
            $orderData['flight_number_song'] = $flight_number_song;
            $orderData['flight_time_song'] = $flight_time_song;
            if($type=="goods"){
                $status=0;//未支付
                //支付到期时间
                $close_hour=0.5;
                $order_ext['pay_expired_time'] = time() + ($close_hour * 60 * 60);

            }else{
                $status=1;//已支付
            }
            if($order_ext){
                $orderData['ext'] = json_encode($order_ext);
            }
            $orderData['status'] = $status;//测试时直接设置成已支付，后期再给为0
            //测试时直接设置成已支付 有确认到期时间
            $orderData['remark'] = $remark;
            $orderData['platform'] = request()->header('platform');
            // $orderData['pay_fee'] = $pay_fee;          // 回调填充
            // $orderData['transaction_id'] = transaction_id;
            // $orderData['payment_json'] = payment_json;
            // $orderData['pay_type'] = pay_type;
            // $orderData['paytime'] = paytime;
            $order = new Order();
            $order->allowField(true)->save($orderData);



//            // 订单创建后
//            $data = [
//                'user' => $user,
//                'order' => $order,
//                'from' => $from,
//                'buy_type' => $buy_type,
//                'activity_type' => $activity_type,
//                'new_goods_list' => $new_goods_list
//            ];
//            \think\Hook::listen('order_create_after', $data);

            // 重新获取订单
            $order = self::where('id', $order['id'])->find();
            return $order;
        });

        return $order;
    }

    // 订单列表
    public static function getList($params)
    {
        $user = User::info();
        extract($params);
        $order = (new self())->where('user_id', $user->id);
        if(isset($keyword)){
            $order=$order->where('goods_title','like','%'.$keyword.'%');
        }
        switch ($type) {
            case 'all':
                $order = $order;
                break;
            case 'nopay':
                $order = $order->nopay();
                break;
            case 'payed':
                $order = $order->payed();
                break;
            case 'cancel':
                $order = $order->cancel();
                break;
            case 'finish_service':
                $order = $order->finishservice();
                break;
        }
        $orders = $order->order('id', 'desc')->paginate(10);

        $orders->each(function ($order){
            $order_ext = $order['ext_arr'];
            $pay_expired_time=$order_ext['pay_expired_time']??0;
            $time=time();
            if($time>=$pay_expired_time){
                $order['pay_expired_second']=0;
            }else{
                $order['pay_expired_second']=$pay_expired_time-$time;
            }
        });
        return $orders;
    }

    // 订单详情
    public static function detail($params)
    {
        $user = User::info();
        extract($params);

        $order = (new self())->where('user_id', $user->id);

        if (isset($order_sn)) {
            $order = $order->where('order_sn', $order_sn);
        }
        if (isset($id)) {
            $order = $order->where('id', $id);
        }

        $order = $order->find();
        $order_ext = $order['ext_arr'];
        $pay_expired_time=$order_ext['pay_expired_time']??0;
        $time=time();
        if($time>=$pay_expired_time){
            $order['pay_expired_second']=0;
        }else{
            $order['pay_expired_second']=$pay_expired_time-$time;
        }

        if (!$order) {
            new Exception('订单不存在');
        }
        return $order;
    }

    /**
     * 支付完成回调
     * @param $order
     * @param $notify
     */
    public function paymentProcess($order, $notify)
    {
        $order->status = Order::STATUS_PAYED;
        $order->paytime = time();
        $order->transaction_id = $notify['transaction_id'];
        $order->payment_json = $notify['payment_json'];
        $order->pay_type = $notify['pay_type'];
        $order->pay_fee = $notify['pay_fee'];
//        $close_hour=12;
//        $order_ext['confirm_expired_time'] = time() + ($close_hour * 60 * 60);
//        $order->ext = json_encode($order->setExt($order, $order_ext));
        $order->save();

//        $user = User::where('id', $order->user_id)->find();
//        \addons\oil\model\OrderAction::operAdd($order, $user, 'user', '用户支付成功','pay');
        // 支付成功后续使用异步队列处理
//        \think\Queue::push('\addons\shopro\job\OrderPayed@payed', ['order' => $order, 'user' => $user], 'shopro-high');
        return $order;
    }

    // 开始退款
    public static function startRefund($order, $refund_money, $user = null, $remark = '') {
        // 订单退款前
        $data = ['order' => $order];
//        \think\Hook::listen('order_refund_before', $data);

        \addons\oil\model\OrderAction::operAdd($order, $user, ($user ? 'admin' : 'system'), $remark . '，退款金额：' . $refund_money);

        \app\admin\model\oil\order\Order::refund($order, $refund_money, $remark);

        // 订单退款后
        $data = ['order' => $order];
        \think\Hook::listen('order_refund_after', $data);
    }

    // 退款
    public static function refund($order, $refund_money, $remark = '')
    {
        // 生成退款单
        $refundLog = new RefundLog();
        $refundLog->order_sn = $order->order_sn;
        $refundLog->refund_sn = RefundLog::getSn($order->user_id);
        $refundLog->pay_fee = $order->pay_fee;
        $refundLog->refund_fee = $refund_money;
        $refundLog->pay_type = $order->pay_type;
        $refundLog->save();

        if ($order->pay_type == 'wechat' || $order->pay_type == 'alipay') {
            // 微信|支付宝退款
            $payOrder=Db::name('sum_pay_order')->where('table_name','sum_oil_order')->where('table_id',$order['id'])->where('ispay',1)->find();
            // 退款数据
            $order_data = [
                'out_trade_no' => $payOrder['out_trade_no']
            ];

            if ($order->pay_type == 'wechat') {
                $total_fee = $order->pay_fee * 100;
                $refund_fee = $refund_money * 100;

                $order_data = array_merge($order_data, [
                    'out_refund_no' => $refundLog->refund_sn,
                    'total_fee' => $total_fee,
                    'refund_fee' => $refund_fee,
                    'refund_desc' => $remark,
                ]);
            } else {
                $order_data = array_merge($order_data, [
                    'out_request_no' => $refundLog->refund_sn,
                    'refund_amount' => $refund_money,
                ]);
            }

            $notify_url = request()->domain() . '/addons/sum/pay/notifyr/payment/' . $order->pay_type . '/platform/' . $order->platform;

            $pay = new \addons\sum\library\PayService($order->pay_type, $order->platform, $notify_url);
            $result = $pay->refund($order_data);

            \think\Log::write('refund-result' . json_encode($result));


            if ($order->pay_type == 'wechat') {
                // 微信通知回调 pay->notifyr
                if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
                    return true;
                } else {
                    throw new \Exception($result['return_msg']);
                }
            } else {
                // 支付宝通知回调 pay->notifyx
                if ($result['code'] == "10000") {
                    return true;
                } else {
                    throw new \Exception($result['msg']);
                }
            }

            // {        // 微信返回结果
            //     "return_code":"SUCCESS",
            //     "return_msg":"OK",
            //     "appid":"wx39cd0799d4567dd0",
            //     "mch_id":"1481069012",
            //     "nonce_str":"huW9eIAb5BDPn0Ma",
            //     "sign":"250316740B263FE53F5DFF50AF5A8FA1",
            //     "result_code":"SUCCESS",
            //     "transaction_id":"4200000497202004072822298902",
            //     "out_trade_no":"202010300857029180027000",
            //     "out_refund_no":"1586241595",
            //     "refund_id":"50300603862020040700031444448",
            //     "refund_channel":[],
            //     "refund_fee":"1",
            //     "coupon_refund_fee":"0",
            //     "total_fee":"1",
            //     "cash_fee":"1",
            //     "coupon_refund_count":"0",
            //     "cash_refund_fee":"1
            // }

            // {        // 支付宝返回结果
            //     "code": "10000",
            //     "msg": "Success",
            //     "buyer_logon_id": "157***@163.com",
            //     "buyer_user_id": "2088902485164146",
            //     "fund_change": "Y",
            //     "gmt_refund_pay": "2020-08-15 16:11:45",
            //     "out_trade_no": "202002460317545607015300",
            //     "refund_fee": "0.01",
            //     "send_back_fee": "0.00",
            //     "trade_no": "2020081522001464141438570535"
            // }
        } else if ($order->pay_type == 'wallet') {
            // 余额退款
            if ($refund_money != 0) {
                \addons\sum\model\User::money($refund_money, $order->user_id, 'wallet_refund', $order->id, '', [
                    'order_id' => $order->id,
                    'order_sn' => $order->order_sn,
                ]);
            }

            self::refundFinish($order, $refundLog);

            return true;
        } else if ($order->pay_type == 'score') {
            // 积分退款，暂不支持积分退款
            return false;
        }
    }
    public static function refundFinish($order, $refundLog)
    {
        // 退款完成
        $refundLog->status = 1;
        $refundLog->save();

        // 退款完成
        $order->refund_status = \app\admin\model\oil\order\Order::REFUND_STATUS_FINISH;    // 退款完成
        $order->save();
        \addons\oil\model\OrderAction::operAdd($order, null, 'admin', '退款成功');
    }
    // 确认加油订单
    public static function operConfirm($params)
    {
        $user = User::info();
        extract($params);
        $order = self::where('user_id', $user->id)->where('id', $id)->noget()->find();
        if (!$order) {
            new Exception('订单不存在或已确认');
        }
        // 订单取消
        $order = (new self)->doConfirm($order, $user);
        return $order;
    }

    /**
     * 确认订单操作
     * @return mixed
     */
    public function doConfirm($order, $user, $type = 'user') {
        $order = Db::transaction(function () use ($order, $user, $type) {
            $data = ['order' => $order];
//            \think\Hook::listen('order_confirm_before', $hookData);

            $order->status = Order::STATUS_FINISH;        // 完成订单
            $order->ext = json_encode($order->setExt($order, ['confirm_time' => time()]));      // 完成时间
            $order->save();



            \addons\oil\model\OrderAction::operAdd($order, $user, $type, ($type == 'user' ? '用户' : '管理员') . '确认订单','confirm');
            $data = ['order' => $order];
            \think\Hook::listen('order_confirm_after', $data);
            return $order;
        });
        return $order;
    }

    // 取消订单
    public static function operCancel($params)
    {
        $user = User::info();
        extract($params);
        $order = self::where('user_id', $user->id)->where('id', $id)->nopay()->find();
        if (!$order) {
            new Exception('订单不存在或已取消');
        }
        // 订单取消
        $order = (new self)->doCancel($order, $user);
        return $order;
    }
    /**
     * 取消订单操作
     * @return mixed
     */
    public function doCancel($order, $user, $type = 'user') {
        $order = Db::transaction(function () use ($order, $user, $type) {
            $data = ['order' => $order];
//            \think\Hook::listen('order_cancel_before', $data);

            $order->status = Order::STATUS_CANCEL;        // 取消订单
            $order->ext = json_encode($order->setExt($order, ['cancel_time' => time()]));      // 取消时间
            $order->save();
//            \addons\oil\model\OrderAction::operAdd($order, $user, $type, ($type == 'user' ? '用户' : '管理员') . '取消订单','cancel');
            // 订单取消，退回使用的用户，等
//            $data = ['order' => $order];
//            \think\Hook::listen('order_cancel_after', $data);
            return $order;
        });
        return $order;
    }


    public function setExt($order, $field, $origin = []) {
        $newExt = array_merge($origin, $field);

        $orderExt = $order['ext_arr'];

        return array_merge($orderExt, $newExt);
    }
}
